package chooongg.base.widget.hText

import android.animation.Animator
import android.animation.ValueAnimator
import android.graphics.Canvas
import android.util.AttributeSet
import android.view.animation.AccelerateDecelerateInterpolator
import java.util.*
import kotlin.math.max

class ScaleText : HText() {

    var mostCount = 20f
    var charTime = 400f
    private val differentList: MutableList<CharacterDiffResult> = ArrayList()
    private var duration: Long = 0
    private var animator: ValueAnimator? = null

    override fun init(hTextView: HTextView?, attrs: AttributeSet?, defStyle: Int) {
        super.init(hTextView, attrs, defStyle)
        animator = ValueAnimator()
        animator!!.interpolator = AccelerateDecelerateInterpolator()
        animator!!.addListener(object : DefaultAnimatorListener() {
            override fun onAnimationEnd(animation: Animator) {
                listener?.onAnimationEnd(mHTextView)
            }
        })
        animator!!.addUpdateListener { animation ->
            progress = animation.animatedValue as Float
            mHTextView!!.invalidate()
        }
        var n = mText!!.length
        n = if (n <= 0) 1 else n
        duration = (charTime + charTime / mostCount * (n - 1)).toLong()
    }

    override fun animateText(text: CharSequence?) {
        if (mHTextView == null || mHTextView!!.layout == null) return
        mHTextView!!.post(Runnable {
            if (mHTextView == null || mHTextView!!.layout == null) {
                return@Runnable
            }
            oldStartX = mHTextView!!.layout.getLineLeft(0)
            super@ScaleText.animateText(text)
        })
    }

    override fun initVariables() {}
    override fun animatePrepare(text: CharSequence?) {
        differentList.clear()
        differentList.addAll(CharacterUtils.diff(mOldText!!, mText!!))
    }

    override fun animateStart(text: CharSequence?) {
        var n = mText!!.length
        n = if (n <= 0) 1 else n
        duration = (charTime + charTime / mostCount * (n - 1)).toLong()
        animator!!.cancel()
        animator!!.setFloatValues(0f, 1f)
        animator!!.duration = duration
        animator!!.start()
    }

    public override fun drawFrame(canvas: Canvas?) {
        val startX = mHTextView!!.layout.getLineLeft(0)
        val startY = mHTextView!!.baseline.toFloat()
        var offset = startX
        var oldOffset = oldStartX
        val maxLength = max(mText!!.length, mOldText!!.length)
        for (i in 0 until maxLength) {
            // draw old text
            if (i < mOldText!!.length) {
                val move = CharacterUtils.needMove(i, differentList)
                if (move != -1) {
                    mOldPaint!!.textSize = mTextSize
                    mOldPaint!!.alpha = 255
                    var p = progress * 2f
                    p = if (p > 1) 1f else p
                    val distX =
                        CharacterUtils.getOffset(i, move, p, startX, oldStartX, gapList, oldGapList)
                    canvas!!.drawText(
                        mOldText!![i].toString() + "",
                        0,
                        1,
                        distX,
                        startY,
                        mOldPaint!!
                    )
                } else {
                    mOldPaint!!.alpha = ((1 - progress) * 255).toInt()
                    mOldPaint!!.textSize = mTextSize * (1 - progress)
                    val width = mOldPaint!!.measureText(mOldText!![i].toString() + "")
                    canvas!!.drawText(
                        mOldText!![i].toString() + "",
                        0,
                        1,
                        oldOffset + (oldGapList[i] - width) / 2,
                        startY,
                        mOldPaint!!
                    )
                }
                oldOffset += oldGapList[i]
            }

            // draw new text
            if (i < mText!!.length) {
                if (!CharacterUtils.stayHere(i, differentList)) {
                    var alpha =
                        (255f / charTime * (progress * duration - charTime * i / mostCount)).toInt()
                    if (alpha > 255) alpha = 255
                    if (alpha < 0) alpha = 0
                    var size =
                        mTextSize * 1f / charTime * (progress * duration - charTime * i / mostCount)
                    if (size > mTextSize) size = mTextSize
                    if (size < 0) size = 0f
                    mPaint!!.alpha = alpha
                    mPaint!!.textSize = size
                    val width = mPaint!!.measureText(mText!![i].toString() + "")
                    canvas!!.drawText(
                        mText!![i].toString() + "",
                        0,
                        1,
                        offset + (gapList[i] - width) / 2,
                        startY,
                        mPaint!!
                    )
                }
                offset += gapList[i]
            }
        }
    }
}